import 'event-target-polyfill';
import 'yet-another-abortcontroller-polyfill'
import { RequestOptionsInit } from 'umi-request';

// 声明一个 Map 用于存储每个请求的标识 和 取消函数
let pendingMap = new Map<string, any>();

// 根据参数序列化，用于生成pendingMap的key
const getPendingUrl = (config: RequestOptionsInit) => [config.method, config.prefix, config.url].join("&");

class RequestAbort {
	/**
	 * @description: 添加请求
	 * @param {Object} config
	 */
	addPending(config: RequestOptionsInit) {
		// 在请求开始前，对之前的请求做检查取消操作
		this.removePending(config);
		const url = getPendingUrl(config);
		const controller = new AbortController(); // 创建一个控制器
		const { signal } = controller; // 返回一个 AbortSignal 对象实例，它可以用来 with/abort 一个 DOM 请求
		config.signal = signal; // 这将信号和控制器与获取请求相关联然后允许我们通过调用 AbortController.abort() 中止请求
		if (!pendingMap.has(url)) {
			pendingMap.set(url, controller);
		}
	}

	/**
	 * @description: 移除请求
	 * @param {Object} config
	 */
	removePending(config: RequestOptionsInit) {
		const url = getPendingUrl(config);
        // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
		if (pendingMap.has(url)) {
			const controller = pendingMap.get(url);
			controller && controller.abort(); // 中止一个尚未完成的请求
			pendingMap.delete(url);
		}
	}

	/**
	 * @description: 清空所有pending
	 */
	removeAllPending() {
		pendingMap.forEach(controller => {
			controller && controller();
		});
		pendingMap.clear();
	}

	/**
	 * @description: 重置
	 */
	reset(): void {
		pendingMap = new Map<string, any>();
	}
}

export default new RequestAbort();